\chapter{QTcpServer}

QTcpServer 类提供了一个基于 TCP 协议的服务器。

\begin{tabular}{|r|l|}
	\hline
	属性 & 方法 \\
	\hline
	头文件 & \#include <QTcpServer>\\      
	\hline
	qmake & QT += network\\      
	\hline
	父类	  & QObject \\ 
	\hline
    子类	 & QSctpServer \\ 
	\hline
\end{tabular}


\begin{notice}
该类的所有成员函数都是可重入的。
\end{notice}

\section{公共成员函数}

\begin{longtable}[l]{|r|l|}
	\hline
		& QTcpServer(QObject *parent = nullptr) \\
	\hline
	 virtual	& $\sim$QTcpServer() \\ 
	\hline
void	 & close() \\ 
\hline
QString	& errorString() const \\
\hline
virtual bool	& hasPendingConnections() const \\ 
\hline
bool	& isListening() const \\ 
\hline
bool	& listen(const QHostAddress \&address = QHostAddress::Any, quint16 port = 0) \\ 
\hline
int	& maxPendingConnections() const \\
\hline
virtual QTcpSocket *	& nextPendingConnection()\\
\hline
void	 & pauseAccepting() \\ 
\hline
QNetworkProxy	& proxy() const\\
\hline
void	 & resumeAccepting()\\
\hline
QHostAddress & 	serverAddress() const\\
\hline
QAbstractSocket::SocketError	 & serverError() const \\
\hline
quint16	 & serverPort() const\\
\hline
void	 & setMaxPendingConnections(int numConnections)\\
\hline
void	 & setProxy(const QNetworkProxy \&networkProxy)\\
\hline
bool	& setSocketDescriptor(qintptr socketDescriptor)\\
\hline
qintptr	& socketDescriptor() const\\
\hline
bool	& waitForNewConnection(int msec = 0, bool *timedOut = nullptr)\\
	\hline
\end{longtable}

\section{信号}

\begin{tabular}{|r|l|}
	\hline
	类型	 & 函数名 \\
	\hline
void	v & acceptError(QAbstractSocket::SocketError \emph{socketError}) \\
\hline
void	 & newConnection() \\
	\hline 
\end{tabular}

\section{保护成员函数}

\begin{tabular}{|r|l|}
	\hline
	类型	 & 函数名 \\
	\hline
void	 &  addPendingConnection(QTcpSocket \emph{*socket}) \\ 
\hline
virtual void	 & incomingConnection(qintptr \emph{socketDescriptor}) \\ 
	\hline 
\end{tabular}

\section{详细介绍}

这个类使“用Qt编写一个接受 TCP 链接的服务器”的构想成为可能。您可以为 QTcpServer 指定一个端口或者让它自动选一个。您也可以令 QTcpServer 仅监听一个指定的地址或者让它监听这台机器上的所有地址。

调用 listen() 函数来为到达的连接建立服务器监听。每次当有新的客户端连接到这个服务端时，QTcpServer 都会发出 newConnection() 信号。

调用 nextPendingConnection() 函数接受一个连接到 QTcpServer 的待处理连接。 该函数会返回一个处于已连接（ QAbstractSocket::ConnectedState ）状态的 QTcpSocket ，您可以使用这个 QTcpSocket 与客户端进行通信。

如果发生错误，serverError() 函数会返回该错误的类型。 您可以调用 errorString() 函数来获取一个能让人看懂的错误描述。

当服务器正在监听连接时，服务器所监听的地址和端口可以通过 serverAddress() 和 serverPort() 函数来获取。

调用 close() 函数后 QTcpServer 会停止监听到达的连接。

\begin{seeAlso}
QTcpSocket、 Fortune Server Example 、Threaded Fortune Server Example 、Loopback Example 和 Torrent Example。
\end{seeAlso}


\section{成员函数文档}

QTcpServer::QTcpServer(QObject  \emph{*parent}= nullptr)

构造函数。构造一个 QTcpServer 对象。

\emph{parent} 参数将传递到 QObject 的构造函数中。

\begin{seeAlso}
listen() 和 setSocketDescriptor()。
\end{seeAlso}


% gog 

[SIGNAL] void QTcpServer::acceptError(QAbstractSocket::SocketError \emph{socketError})

当接受一个新的连接时出错，QTcpServer 会发送此信号。 socketError 参数描述了该错误的类型。

该函数最早在Qt5.0版本引入。

\begin{seeAlso}
pauseAccepting() 和 resumeAccepting()。
\end{seeAlso}

[SIGNAL] void QTcpServer::newConnection()

每当有新的连接可用时，QTcpServer 都会发送该消息。

\begin{seeAlso}
hasPendingConnections() 和 nextPendingConnection()。
\end{seeAlso}

[virtual] QTcpServer::$\sim$QTcpServer()

析构函数。销毁 QTcpServer 对象。如果服务器正在监听连接，套接字会自动关闭。

在服务端删除之前，所有仍处于连接状态的客户端 QTcpSocket 都必须断开连接或者重新指定父类。

\begin{seeAlso}
 close() 。
\end{seeAlso}


[protected] void QTcpServer::addPendingConnection(QTcpSocket  \emph{*socket})

该函数由 QTcpServer::incomingConnection() 函数调用，作用是添加 socket 到待处理连接列表中。

\begin{notice}
如果您不想破坏连接处理机制，请不要忘记从重新实现的 incomingConnection() 中调用此成员。
\end{notice}

该函数最初在Qt4.7版本引入。

\begin{seeAlso}
incomingConnection() 
\end{seeAlso}

void QTcpServer::close()

关闭服务器。服务器将不再监听到达的连接。

\begin{seeAlso}
 listen() 
\end{seeAlso}

QString QTcpServer::errorString() const

将最后一个出现的错误的相关信息按照适合人阅读的形式返回。


\begin{seeAlso}
serverError() 
\end{seeAlso}


[virtual] bool QTcpServer::hasPendingConnections() const

当服务端有待处理的连接时该函数返回 true ，否则返回 false 。

\begin{seeAlso}
nextPendingConnection() 和 setMaxPendingConnections()。
\end{seeAlso}

[virtual protected] void QTcpServer::incomingConnection(qintptr \emph{socketDescriptor})

当有新的连接到达时， QTcpServer 会调用该虚函数。 socketDescriptor 参数是为该连接指定的本机套接字描述符。

对该虚函数重写，您需要进行以下操作：

\begin{compactitem}
\item 构建一个 QTcpSocket 。
\item 设置套接字描述符。
\item 将 QTcpSocket 储存在内部的待处理连接列表中。
\item 发送 newConnection() 信号。
\end{compactitem}

重写此函数，以在连接可用时更改服务器的行为。

如果该服务器使用了 QNetworkProxy ，\emph{socketDescriptor}可能并不能被本地套接字功能使用，应该仅被 QTcpSocket::setSocketDescriptor() 函数使用。

\begin{notice}
	如果在这个方法中创建了另外一个套接字，该套接字需要通过调用 addPendingConnection() 函数添加到连接处理机制中。

\end{notice}

\begin{notice}
	如果您想在另外一个线程中将到达的连接当作一个新的 QTcpSocket 进行处理，您需要将套接字描述符传递到那个线程中并在那个线程中创建一个 QTcpSocket 对象并使用该该对象的 setSocketDescriptor() 方法。
\end{notice}

\begin{notice}
	如果您想在另外一个线程中将到达的连接当作一个新的 QTcpSocket 进行处理，您需要将套接字描述符传递到那个线程中并在那个线程中创建一个 QTcpSocket 对象并使用该该对象的 setSocketDescriptor() 方法。
\end{notice}

\begin{seeAlso}
newConnection(), nextPendingConnection() 和 addPendingConnection()。
\end{seeAlso}

bool QTcpServer::isListening() const

当服务端正在监听连接时返回 true ，否则返回 false 。

\begin{seeAlso}
listen()。
\end{seeAlso}

bool QTcpServer::listen(const QHostAddress  \emph{\&address} = QHostAddress::Any, quint16 \emph{port} = 0)

令服务端监听在 address 指定的地址和 port 指定的端口上到达的连接。如果 port 参数为0 ，QTcpServer 会自动选择一个端口。 如果 address 参数为 QHostAddress::Any ，服务端会监听所有的网络接口。

操作成功该函数返回 true ，否则返回 false 。

\begin{seeAlso}
isListening() 
\end{seeAlso}

int QTcpServer::maxPendingConnections() const

返回最大的待处理的已接受连接数。默认为30。

\begin{seeAlso}
setMaxPendingConnections() 和 hasPendingConnections() 。
\end{seeAlso}


[virtual] QTcpSocket *QTcpServer::nextPendingConnection()

将下一个待处理的连接作为已连接的 QTcpSocket 对象返回。

该套接字将作为该服务端的子对象创建，这就意味着当 QTcpServer 对象销毁后，该套接字对象也会被销毁。最好在完成处理后显式删除该对象，以避免浪费内存。

如果没有待处理的连接，该函数会返回 nullptr 。

\begin{notice}
返回的 QTcpSocket 对象不能在其他线程中使用。如果您想在其他的线程中使用到达的连接，您需要重写 incomingConnection() 函数。
\end{notice}
 
\begin{seeAlso}
hasPendingConnections() 。
\end{seeAlso}

void QTcpServer::pauseAccepting()

暂停接收新连接。队列连接会保留在队列中。

该函数最初在Qt5.0版本引入。

\begin{seeAlso}
resumeAccepting()
\end{seeAlso}


QNetworkProxy QTcpServer::proxy() const

返回该套接字的网络代理。默认将使用QNetworkProxy::DefaultProxy 。

该函数最初在Qt4.1版本引入。


\begin{seeAlso}
setProxy() 和 QNetworkProxy()。
\end{seeAlso}

void QTcpServer::resumeAccepting()

恢复接收新连接。

该函数最初在Qt5.0版本引入。

\begin{seeAlso}
pauseAccepting()。
\end{seeAlso}

QHostAddress QTcpServer::serverAddress() const

如果服务端正在监听，则返回服务端的地址，否则返回 QHostAddress::Null 。

\begin{seeAlso}
serverPort() 和 listen() 。
\end{seeAlso}


QAbstractSocket::SocketError QTcpServer::serverError() const

返回最后出现的错误的代码。

\begin{seeAlso}
errorString()。
\end{seeAlso}

quint16 QTcpServer::serverPort() const

如果服务端正在监听，则返回服务端的端口，否则返回 0 。

\begin{seeAlso}
serverAddress() 和 listen() 。
\end{seeAlso}

void QTcpServer::setMaxPendingConnections(int \emph{numConnections})

设置待处理的已接受连接的数目最大值为 \emph{numConnections}。超过该数目后，在调用 nextPendingConnection() 函数之前， QTcpServer 将不会再接收到达的连接。默认情况下，QTcpServer接收连接的最大值为30。

服务器达到其最大待处理连接数后，客户端仍然可以连接（即 QTcpSocket 仍可以发出 connected() 信号）。 QTcpServer 将停止接受新连接，但是操作系统仍可以将它们保持在队列中。

\begin{seeAlso}
maxPendingConnections() 和 hasPendingConnections() 。
\end{seeAlso}

void QTcpServer::setProxy(const QNetworkProxy \emph{\&networkProxy} )

显式设置该套接字的网络代理为 \emph{networkProxy} 。

您通过设置使用 QNetworkProxy::NoProxy 代理类型来禁止套接字使用代理：

\begin{cppcode}
server->setProxy(QNetworkProxy::NoProxy);
\end{cppcode}

该函数最初在Qt4.1版本时引入。

\begin{seeAlso}
proxy() 和 QNetworkProxy。
\end{seeAlso}

bool QTcpServer::setSocketDescriptor(qintptr \emph{socketDescriptor})

设置该服务端监听连接时使用的套接字描述符为 \emph{socketDescriptor} 。当操作成功时返回 true ，否则返回 false 。

调用该函数时，服务端应该处于正在监听的状态。

\begin{seeAlso}
socketDescriptor() 和 isListening()。
\end{seeAlso}



qintptr QTcpServer::socketDescriptor() const

返回服务端监听连接时使用的套接字描述符，如果该服务器未处于监听状态返回-1。

如果服务器正在使用 QNetworkProxy ，返回的套接字描述符可能并不能在本地套接字函数中使用。

\begin{seeAlso}
setSocketDescriptor() 和 isListening()。
\end{seeAlso}


bool QTcpServer::waitForNewConnection(int \emph{msec} = 0, bool \emph{*timedOut} = nullptr)

等待 msec 毫秒或者直到有新的连接接入。如果有新的连接，该函数返回 true ， 否则返回 false 。如果 \emph{*timeOut} 参数不为 nullptr 并且操作超时， \emph{timeOut} 将被设置为 true 。

这是一个可以引起阻塞的函数。不推荐在一个单线程的 GUI 程序中使用该函数，因为使用该函数后直到该函数返回之前整个应用程序会停止响应。 waitForNewConnection() 函数通常在没有事件循环的情况下使用。

不阻塞应用程序的可选方案是使用 newConnection() 信号。

如果 msec 参数设置为-1，该函数将不会超时。

\begin{seeAlso}
hasPendingConnections() 和 nextPendingConnection()。
\end{seeAlso}







